package com.workingpub.commons.jdbc.internal;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.osgi.io.OsgiBundleResource;
import org.springframework.osgi.io.OsgiBundleResourcePatternResolver;

import com.workingpub.commons.jdbc.config.SqlDefineResolver;

public class DefaultSqlMappingListener implements SqlMappingListener, InitializingBean {
	private static final Logger logger = LoggerFactory.getLogger(DefaultSqlMappingListener.class);
	private SqlDefineResolver sqlDefineResolver;
	public static final String DEFAULT_CONFIG_LOCATION = OsgiBundleResource.BUNDLE_URL_PREFIX
			+ "/META-INF/sqlmapping/*.xml";

	@Override
	public void bundleChanged(BundleEvent event) {
		Bundle bundle = event.getBundle();
		if (BundleEvent.STARTED == event.getType()) {
			scanBundleConfig(bundle);
		} else if (BundleEvent.STOPPED == event.getType()) {
			removeBundleConfig(bundle);
		}
	}

	private void removeBundleConfig(Bundle bundle) {
		if (null == bundle) {
			return;
		}
		try {

			ResourcePatternResolver resourceLoader = new OsgiBundleResourcePatternResolver(bundle);
			Resource[] resources = resourceLoader.getResources(DEFAULT_CONFIG_LOCATION);
			if (null == resources || resources.length == 0) {
				logger.info("Did not fount sqlmapping configs, in bundle : " + bundle.getSymbolicName());
				return;
			}
			for (Resource entry : resources) {
				logger.info("SqlMapping resource : " + entry + " in bundle : " + bundle.getSymbolicName());
				try {
					sqlDefineResolver.removeDefine(entry.getInputStream());
				} catch (Exception ex) {
					logger.warn("Failed to resolved sql mapping config : " + ex.getMessage());
				}
			}
		} catch (Throwable e) {
			logger.warn("Failed to load bundle config for sqlmapping : " + e.getMessage(), e);
		}
	}

	@Override
	public void scanBundleConfig(Bundle bundle) {
		if (null == bundle) {
			return;
		}
		try {
			ResourcePatternResolver resourceLoader = new OsgiBundleResourcePatternResolver(bundle);
			Resource[] resources = resourceLoader.getResources(DEFAULT_CONFIG_LOCATION);
			if (null == resources || resources.length == 0) {
				logger.info("Did not fount sqlmapping configs, in bundle : " + bundle.getSymbolicName());
				return;
			}
			for (Resource entry : resources) {
				logger.info("SqlMapping resource : " + entry + " in bundle : " + bundle.getSymbolicName());
				try {
					sqlDefineResolver.addSqlDefine(entry.getInputStream());
				} catch (Exception ex) {
					logger.warn("Failed to resolved sql mapping config : " + ex.getMessage());
				}
			}
		} catch (Throwable e) {
			logger.warn("Failed to load bundle config for sqlmapping : " + e.getMessage(), e);
		}
	}

	public void setSqlDefineResolver(SqlDefineResolver sqlDefineResolver) {
		this.sqlDefineResolver = sqlDefineResolver;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		FrameworkUtil.getBundle(getClass()).getBundleContext().addBundleListener(this);
	}
}
